package com.example.nonacademic_education.service.impl;

import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.nonacademic_education.constant.Constant;
import com.example.nonacademic_education.constant.KapchaCode;
import com.example.nonacademic_education.constant.SingleFactory;
import com.example.nonacademic_education.dao.*;
import com.example.nonacademic_education.data.request.LoginR;
import com.example.nonacademic_education.data.response.AdminIdAndName;
import com.example.nonacademic_education.data.response.AdminVo;
import com.example.nonacademic_education.data.response.StudentDto;
import com.example.nonacademic_education.data.response.StudentUserDto;
import com.example.nonacademic_education.data.sys.Login;
import com.example.nonacademic_education.entity.Admin;
import com.example.nonacademic_education.service.AdminService;
import com.example.nonacademic_education.util.IpUtil;
import com.example.nonacademic_education.util.R;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author xinmiao
 * @description
 * @date 2023/3/28 14:46
 */
@Service
public class AdminServiceImpl extends ServiceImpl<AdminDao, Admin> implements AdminService {
    @Resource
    private AdminDao adminDao;
    @Resource
    private KapchaCode kapchaCode;
    @Resource
    private IpUtil ipUtil;
    @Resource
    private AnyConstantDao anyConstantDao;
    @Resource
    private AdminAuthorityDao adminAuthorityDao;
    @Resource
    private AuthorityDao authorityDao;
    @Resource
    private StudentDao studentDao;

    @Override
    public R getList(Integer page, Integer size, String name, Long departmentId) {
        //这是之后改动的，王老师说，默认查看所有管理员,并且展示最新添加的，即ID倒序排
        if (departmentId==0L){
            departmentId=null;
        }
        if (page < 1) {
            return R.error("page couldn't less than 1");
        } else {
            page = (page - 1) * size;
            Map<String, Object> data = new HashMap<>();
            data.put("list", adminDao.getListByNameAndDepartment(page, size, name, departmentId));
            data.put("total", adminDao.countByNameAndDepartment(name, departmentId));
            return R.ok(data, "getList");
        }
    }

    @Override
    public R addOne(Admin admin) {
        String authority;
        admin.setId(null);
        //admin.setPassword(Constant.DEFAULT_PASSWORD);
        admin.setPassword(BCrypt.hashpw(Constant.DEFAULT_PASSWORD, BCrypt.gensalt(4)));
        admin.setIsDel(0);
        if (admin.getDepartmentId() == null) {
            admin.setDepartmentId(0L);
            admin.setAuthority("2");
            authority = anyConstantDao.getValueById(2L);
        } else {
            admin.setAuthority("1");
            authority = anyConstantDao.getValueById(3L);
        }
        adminDao.addOne(admin);
        Long id=adminDao.getIdByUsername(admin.getUsername());
        List<Long> authorities= Arrays.stream(authority.split(","))
                .map(Long::valueOf)
                .collect(Collectors.toList());
        adminAuthorityDao.addAuthority(id,authorities);
        return R.ok("addOne");
    }

    @Override
    public R updateOne(Admin admin) {
        if (admin.getId() == null) {
            return R.error("id is null");
        }
        adminDao.updateOneById(admin);
        return R.ok("updateOne");
    }

    @Override
    public R deleteOne(Long id) {
        adminDao.deleteOneById(id);
        adminAuthorityDao.deleteByAdminId(id);
        return R.ok("deleteOne");
    }

    @Override
    public R login(LoginR admin, HttpServletRequest request) {
        AdminVo at=adminDao.getOneByUsername(admin.getUsername());
        if (at==null){
            return R.error("您输入的账号不存在！");
        }
        if (at.getAble()==0){
            boolean disable = StpUtil.isDisable(admin.getUsername());
            if (disable) {
                long disableTime = StpUtil.getDisableTime(admin.getUsername())/60;
                return R.error("您的账号已被系统自动封禁，剩余时间 "+disableTime/60+" 小时 "+disableTime%60+" 分钟，请联系管理员处理！");
            }
            return R.error("您的账号已被管理员永久封禁，请联系管理员处理！");
        }
        if (admin.getCode() == null) {
            return R.error("请输入验证码");
        }
//        String ip = ipUtil.getIpAddr(request);
//        if (ip.equals("")) {
//            return R.error("请关闭代理");
//        }
        if (kapchaCode.getCodes().get(admin.getCode())==null) {
            return R.error("验证码错误或已过期");
        }
        String password=adminDao.getPasswordByUsername(admin.getUsername());
        boolean result = BCrypt.checkpw(admin.getPassword(),password);
        if (result) {
            AdminVo a = adminDao.findOneByUsernameAndPassword(admin.getUsername(), admin.getPassword());
            StpUtil.login(admin.getUsername());
            Map<String, Object> data = new HashMap<>();
            data.put("user", a);
            data.put("token", StpUtil.getTokenValue());
            //log.error(StpUtil.getLoginId().toString());
            kapchaCode.getCodes().remove(admin.getCode());
            return R.ok(data, "success");
        }
        //累加错误次数
        Login login = SingleFactory.getInstance().getLogins().get(admin.getUsername());
        if (login==null){
            login=new Login();
            login.setCnt(1);
            login.setUsername(admin.getUsername());
        }else {
            if (login.getCnt()>=5){
                SingleFactory.getInstance().getLogins().remove(admin.getUsername());
                // 先踢下线
                StpUtil.kickout(admin.getUsername());
                // 再封禁账号,86400是1天
                StpUtil.disable(admin.getUsername(), 86400/4);
                enableAccount(admin.getUsername(),0);
                login.setCnt(-1);
                SingleFactory.getInstance().getLogins().put(admin.getUsername(), login);
                return R.error("错误次数太多，您的账号已被系统封禁！");
            }
            if(login.getLoginTime()-System.currentTimeMillis()<30000L){
                login.setCnt(login.getCnt()+1);
            }
        }
        login.setLoginTime(System.currentTimeMillis());
        SingleFactory.getInstance().getLogins().put(admin.getUsername(), login);
        return R.error("账号密码不正确");
    }

    @Override
    public R getAdminByName(String name, Long departmentId) {
        if (departmentId==null){
            departmentId=adminDao.getDepartmentIdByUsername(StpUtil.getLoginIdAsString());
        }
        List<AdminIdAndName> list = adminDao.getOneByName(name, departmentId);
        if (list == null) {
            return R.error("未查询到数据");
        }
        Map<String, Object> data = new HashMap<>();
        data.put("users", list);
        return R.ok(data, "查询成功");
    }

    @Override
    public R updateOneself(Admin admin) {
        if (admin.getId() == null) {
            return R.error("id is null");
        }
        adminDao.updateOneself(admin);
        return R.ok("updateOneself");
    }

    @Override
    public R resetPassword(LoginR loginR) {
        if(loginR.getPassword()==null||loginR.getPassword().equals("")) {
            loginR.setPassword(Constant.DEFAULT_PASSWORD);
        }
        loginR.setPassword(BCrypt.hashpw(loginR.getPassword(), BCrypt.gensalt(4)));
        if (adminDao.resetPassword(loginR.getUsername(), loginR.getPassword()) > 0) {
            return R.ok("修改密码成功");
        } else {
            return R.error("修改密码失败");
        }
    }

    @Override
    public R getPersonalInfo() {
        String username;
        try {
            username=StpUtil.getLoginId().toString();
        }catch (Exception e) {
            return R.error("登录信息过期，请重新登录");
        }
        AdminVo a = adminDao.getOneByUsername(username);
        Map<String, Object> data = new HashMap<>();
        if (a != null) {
            if(a.getDepartmentId()==0L){
                a.setDepartmentId(null);
            }
            data.put("user", a);
            StringBuffer authority=new StringBuffer();
            List<Long> byAdminId = adminAuthorityDao.findByAdminId(a.getId());
            if (!byAdminId.isEmpty()){
                List<String> valueByIds = authorityDao.getValueByIds(byAdminId);
                for (int i=0;i< valueByIds.size();i++){
                    if (i==0){
                        authority.append(valueByIds.get(i));
                    }else {
                        authority.append(",").append(valueByIds.get(i));
                    }
                }
            }else {
                return R.error("获取权限失败");
            }
            data.put("authority", authority.toString());
            return R.ok(data, "获取个人信息成功");
        }else {
            StudentUserDto studentUserDto=studentDao.getOneByUsername(StpUtil.getLoginIdAsString());
            if (studentUserDto==null) {
                return R.error( "获取个人信息失败");
            }else {
                if (studentUserDto.getIdentificationPhotoUrl() == null) {
                    StudentUserDto s = studentDao.getOneHaveUrl(StpUtil.getLoginIdAsString());
                    if (s != null) {
                        studentDao.updateUrlByUsername(s.getIdentityCardId(), s.getIdentificationPhotoUrl());
                        studentUserDto.setIdentificationPhotoUrl(s.getIdentificationPhotoUrl());
                    }
                }
                studentUserDto.setAuthority(Constant.STUDENT);
                data.put("user",studentUserDto);
                return R.ok(data, "获取个人信息成功");
            }
        }
    }

    @Override
    public R resetAdminPassword(String username) {
        if (adminDao.resetPassword(username,BCrypt.hashpw(Constant.DEFAULT_PASSWORD, BCrypt.gensalt(4)))>0){
            return R.ok("重置管理员密码成功!");
        }else {
            return R.error("重置管理员密码失败!");
        }
    }

    @Override
    public R enableAccount(String id, int able) {
        adminDao.enableAccount(id, able);
        if (able==1){
            if (StpUtil.isDisable(id)){
                StpUtil.untieDisable(id);
            }
            return R.ok("解封账号成功");
        }else {
            return R.ok("封禁账号成功");
        }
    }
    // TODO: 2023/5/29 删除个人证件照
}
